package com.ykt.controller;

import com.jfinal.ext.route.ControllerBind;
import com.jfinal.kit.PropKit;
import com.jfinal.upload.UploadFile;
import com.ykt.common.config.CommonConfigs;
import com.ykt.common.utils.FileUtil;
import com.ykt.exception.BusinessException;
import com.ykt.model.User;
import com.ykt.vo.ResultStatus;
import com.ykt.vo.ResultVo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件上传
 *
 * @author long.hua
 * @version 1.0.0
 * @since 2015-12-23 00:10
 */
@ControllerBind(controllerKey="/upload")
public class UploadController extends BaseController<User> {
    private final static Logger LOGGER = LoggerFactory.getLogger(UploadController.class);

    private static String homeDir = PropKit.get("upload.root.dir");
    private static String domainDir = PropKit.get("download.domain");

    // 图片文件扩展名
    private static final String[] imageFileTypes = new String[]{"gif", "jpg", "jpeg", "png", "bmp"};
    // 视频文件扩展名
    private static final String[] videoFileTypes = new String[]{"avi", "flv", "mp4"};
    // 普通文件扩展名
    private static final String[] normalFileTypes = new String[]{"doc", "docx", "xls", "xlsx", "ppt", "pptx", "pdf", "txt","apk"};
    // 压缩文件扩展名
    private static final String[] compactFileTypes = new String[]{"rar", "zip", "war", "jar", "7z", "tar"};
    // Android安装包扩展名
//    private static final String[] androidFileTypes = new String[]{"apk"};

    public UploadController() {
        super(User.class);
    }
    
    /** 上传单个或多个文件 */
    //@Before(UploadValidator.class)
    public void upload() {
        Map<String, Object> resultMap = new HashMap<>();

        List<UploadFile> uploadFiles = this.getFiles();
        if (uploadFiles == null || uploadFiles.isEmpty()) {
            ResultVo vo = new ResultVo(ResultStatus.FILE_UPLOAD_FAIL, ResultStatus.FILE_UPLOAD_FAIL_MSG);
            renderJson(vo);
            return;
        }

        StringBuilder filePaths = new StringBuilder();

        for (UploadFile uploadFile : uploadFiles) {
            File file = uploadFile.getFile();
            String bizType = getPara("bizType");
            String fileType = getPara("fileType"); // 校验文件类型

            String fileName = uploadFile.getOriginalFileName();
            String extName = FileUtil.getExtName(fileName); // 校验文件后缀

            if (!match(fileType, extName)) {
                LOGGER.warn("指定文件类型与其后缀不匹配，文件类型：{}，文件后缀：{}", fileName, extName);
                throw new BusinessException(ResultStatus.FILE_FORMAT_ERROR, ResultStatus.FILE_UPLOAD_FAIL_MSG);
            }

            String newFileName = FileUtil.newFileName(fileName);
            String relativeDir = getDir(bizType, fileType);
            String relativePath = relativeDir + "/" + newFileName;
            String filePath = homeDir + relativePath;
            File dir = new File(homeDir + relativeDir);
            if (!dir.exists()) {
                boolean flag = dir.mkdirs();
                if (!flag) {
                    LOGGER.warn("创建保存上传文件的目录失败，目录为：", dir.getAbsolutePath());
                    throw new BusinessException(ResultStatus.MAKE_DIR_ERROR, ResultStatus.MAKE_DIR_ERROR_MSG);
                }
            }

            FileInputStream in = null;
            try {
                in = new FileInputStream(file);
                FileUtil.write(in, filePath);

                filePaths.append(domainDir).append(relativePath).append(",");

            } catch (Exception e) {
                LOGGER.error("保存上传的文件异常，文件存储全路径：{}", filePath);
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        LOGGER.error("保存上传的文件异常，文件存储全路径：{}", filePath);
                    }
                }
            }
        }

        // 删除最后一个逗号
        if (filePaths.length() > 0) {
            filePaths.deleteCharAt(filePaths.length() - 1);
        }

        resultMap.put("urls", filePaths.toString());
        ResultVo vo = ResultVo.success(resultMap);

        this.renderJson(vo);
    }

    private String getDir(String bizType, String fileType) {
        String fileTypeDir = CommonConfigs.UploadFileType.valueOf(fileType).getDir();
        String dateDir = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

        switch (CommonConfigs.UploadBizType.valueOf(bizType)) {
            case SHOP:
                return CommonConfigs.UploadBizType.SHOP.getDir() + fileTypeDir + dateDir;
            case HEAD:
                return CommonConfigs.UploadBizType.HEAD.getDir() + fileTypeDir + dateDir;
            case GOODS:
                return CommonConfigs.UploadBizType.GOODS.getDir() + fileTypeDir + dateDir;
            default:
                return CommonConfigs.UploadBizType.OTHER.getDir() + fileTypeDir + dateDir;
        }
    }

    private boolean match(String fileType, String extName) {
        if(extName == null || extName.isEmpty()){
            return false;
        }
        extName = extName.substring(1); // 去符号“.”

        switch (CommonConfigs.UploadFileType.valueOf(fileType)) {
            case VIDEO:
                for (String videoFileType : videoFileTypes) {
                    if (videoFileType.equalsIgnoreCase(extName)) {
                        return true;
                    }
                }
                break;
            case IMAGE:
                for (String imageFileType : imageFileTypes) {
                    if (imageFileType.equalsIgnoreCase(extName)) {
                        return true;
                    }
                }
                break;
            case NORMAL:
                for (String normalFileType : normalFileTypes) {
                    if (normalFileType.equalsIgnoreCase(extName)) {
                        return true;
                    }
                }
                break;
            case COMPACT:
                for (String compactFileType : compactFileTypes) {
                    if (compactFileType.equalsIgnoreCase(extName)) {
                        return true;
                    }
                }
                break;
            default:
                return false;
        }

        return false;
    }


}
